package com.dqx.haoqiu.mvp.common.webview.vassonic;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.net.http.SslError;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.webkit.SslErrorHandler;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceError;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebSettings;
import android.webkit.WebStorage;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;

import androidx.annotation.RequiresApi;

import com.dqx.haoqiu.mvp.R;
import com.dqx.haoqiu.mvp.common.base.BaseActivity;
import com.tencent.bugly.crashreport.CrashReport;
import com.tencent.sonic.sdk.SonicConstants;
import com.tencent.sonic.sdk.SonicEngine;
import com.tencent.sonic.sdk.SonicSession;
import com.tencent.sonic.sdk.SonicSessionConfig;
import com.tencent.sonic.sdk.SonicSessionConnection;
import com.xmjs.baselibrary.base.IBasePresenter;
import com.xmjs.baselibrary.utils.Logger;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 使用腾讯VasSonic框架来提升WebView的加载速度
 */
public class VasSonicActivity extends BaseActivity {
    private RelativeLayout rl;
    private WebView webView;
    private ProgressBar progressBar;
    private SonicSession sonicSession;

    private ValueCallback<Uri> mUploadMessage;
    private ValueCallback<Uri[]> uploadMessage;
    public static final int REQUEST_SELECT_FILE = 100;
    private final static int FILECHOOSER_RESULTCODE = 2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //初始化SonicSessionConfig对象，这个类的作用是设置超时时间、缓存大小等相关参数
        SonicSessionConfig sessionConfig = new SonicSessionConfig.Builder().build();
        //预加载
        boolean preloadSuccess = SonicEngine.getInstance().preCreateSession(setUrl(), sessionConfig);

        SonicSessionClientImpl sonicSessionClient = null;
        SonicSessionConfig.Builder sessionConfigBuilder = new SonicSessionConfig.Builder();

        //使用LocalServer模式，在业务后台无法及时支持时，通过终端模拟server，提供本该后台支持的能力。
        sessionConfigBuilder.setSupportLocalServer(true);
        sessionConfigBuilder.build();

        //创建会话
        sonicSession = SonicEngine.getInstance().createSession(setUrl(), sessionConfigBuilder.build());
        if (null != sonicSession) {
            sonicSession.bindClient(sonicSessionClient = new SonicSessionClientImpl());
        } else {
            //当同一个会话已经执行时
            Logger.i("create sonic session fail!");
        }

        super.setContentView(R.layout.activity_webview);

        rl = findViewById(R.id.rl);
        webView = findViewById(R.id.web_view);
        progressBar = findViewById(R.id.progressBar);

        webView.setWebViewClient(webViewClient);
        webView.setWebChromeClient(webChromeClient);
        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        webSettings.setAllowContentAccess(true);
        webSettings.setDatabaseEnabled(true);
        webSettings.setDomStorageEnabled(true);
        webSettings.setAppCacheEnabled(true);
        webSettings.setSavePassword(false);
        webSettings.setSaveFormData(false);
        webSettings.setDisplayZoomControls(false);
        // webView.setWebContentsDebuggingEnabled(true);
        // 5.0以上允许加载http和https混合的页面
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP)
            webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);

        if (sonicSessionClient != null) {
            //绑定WebView
            sonicSessionClient.bindWebView(webView);
            sonicSessionClient.clientReady();
        } else {
            webView.loadUrl(setUrl());
        }
    }

    WebViewClient webViewClient = new WebViewClient() {

        //html加载完成
        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            if (sonicSession != null) {
                sonicSession.getSessionClient().pageFinish(url);
            }

            //对图片进行重置大小，宽度就是手机屏幕宽度，高度根据宽度比便自动缩放
            webView.loadUrl("javascript:(function(){"
                    + "var objs = document.getElementsByTagName('img'); "
                    + "for(var i=0;i<objs.length;i++)  "
                    + "{"
                    + "var img = objs[i];   "
                    + "    img.style.maxWidth = '100%'; img.style.height = 'auto';  "
                    + "}"
                    + "})()");
        }

        //加载资源请求时，进行拦截
        @TargetApi(21)
        @Override
        public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
            return shouldInterceptRequest(view, request.getUrl().toString());
        }

        //加载资源请求时，进行拦截
        @Override
        public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
            if (sonicSession != null) {
                return (WebResourceResponse) sonicSession.getSessionClient().requestResource(url);
            }
            return null;
        }

        /* 7.0以上 */
        @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
            String url = request.getUrl().toString();
            if (url.startsWith("http") || url.startsWith("https")) { //http和https协议开头的执行正常的流程
                webView.loadUrl(url);
                return true;
            } else { //其他的URL则会开启一个Acitity或去调用原生APP
                try {
                    Intent in = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
                    startActivity(in);
                } catch (Exception e) {
                    toast(R.string.open_failure);
                    if (webView.canGoBack())
                        webView.goBack();
                }
                return true;
            }
        }

        /* 7.0以下*/
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            if (url.startsWith("http") || url.startsWith("https")) { //http和https协议开头的执行正常的流程
                webView.loadUrl(url);
                return true;
            } else { //其他的URL则会开启一个Acitity或调用原生APP
                try {
                    Intent in = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
                    startActivity(in);
                } catch (Exception e) {
                    toast(R.string.open_failure);
                    if (webView.canGoBack())
                        webView.goBack();
                }
                return true;
            }
        }

        //页面加载开始
        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
        }

        //页面加载发生错误
        @RequiresApi(api = Build.VERSION_CODES.M)
        @Override
        public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
            super.onReceivedError(view, request, error);
            showError(R.mipmap.img_error, R.string.error_loading, R.string.refresh);
            loadingFailure();
        }

        //证书验证错误
        @Override
        public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
            //接受所有网站的证书
            handler.proceed();
        }
    };

    WebChromeClient webChromeClient = new WebChromeClient() {
        //扩充缓存的容量
        @Override
        public void onReachedMaxAppCacheSize(long spaceNeeded, long totalUsedQuota,
                                             WebStorage.QuotaUpdater quotaUpdater) {
            quotaUpdater.updateQuota(spaceNeeded * 2);
        }

        @Override
        public void onProgressChanged(WebView view, int newProgress) {
            CrashReport.setJavascriptMonitor(view, true);
            if (newProgress == 100) {//加载完成
                progressBar.setVisibility(View.GONE);
                webView.getSettings().setBlockNetworkImage(false);
                loadingSuccess();
            } else {//加载中
                if (View.GONE == progressBar.getVisibility())
                    progressBar.setVisibility(View.VISIBLE);
                progressBar.setProgress(newProgress);
                loading(newProgress);
            }
        }

        // 兼容3.0+
        protected void openFileChooser(ValueCallback uploadMsg, String acceptType) {
            mUploadMessage = uploadMsg;
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("image/*");
            startActivityForResult(Intent.createChooser(i, "File Browser"), FILECHOOSER_RESULTCODE);
        }

        // 兼容5.0+
        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        public boolean onShowFileChooser(WebView mWebView, ValueCallback<Uri[]> filePathCallback,
                                         FileChooserParams fileChooserParams) {
            if (uploadMessage != null) {
                uploadMessage.onReceiveValue(null);
                uploadMessage = null;
            }
            uploadMessage = filePathCallback;
            Intent intent = fileChooserParams.createIntent();
            try {
                startActivityForResult(intent, REQUEST_SELECT_FILE);
            } catch (ActivityNotFoundException e) {
                uploadMessage = null;
                return false;
            }
            return true;
        }

        protected void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
            mUploadMessage = uploadMsg;
            Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            intent.setType("image/*");
            startActivityForResult(Intent.createChooser(intent, "File Browser"), FILECHOOSER_RESULTCODE);
        }

        protected void openFileChooser(ValueCallback<Uri> uploadMsg) {
            mUploadMessage = uploadMsg;
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("image/*");
            startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE);
        }
    };

    /**
     * 添加JS接口
     *
     * @param obj
     * @param interfaceName
     */
    @SuppressLint("JavascriptInterface")
    public void addJavascriptInterface(Object obj, String interfaceName) {
        webView.addJavascriptInterface(obj, interfaceName);
    }

    /**
     * 调用JS方法
     *
     * @param fuction  方法名
     * @param callback 回调
     */
    public void js(String fuction, ValueCallback<String> callback) {
        webView.post(() -> {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                webView.evaluateJavascript(fuction, callback);
            } else {
                webView.loadUrl("javascript:" + fuction);
            }
        });
    }

    @Override
    public void onReload() {
        super.onReload();
        //重新加载页面
        webView.loadUrl(setUrl());
    }

    /**
     * web加载成功
     */
    public void loadingSuccess() {

    }

    /**
     * web加载中
     *
     * @param progress
     */
    public void loading(int progress) {

    }

    /**
     * 加载失败
     */
    public void loadingFailure() {

    }

    public String setUrl() {
        return "";
    }

    public WebView getWebView() {
        return webView;
    }

    private static class OfflinePkgSessionConnection extends SonicSessionConnection {

        private final WeakReference<Context> context;

        public OfflinePkgSessionConnection(Context context, SonicSession session, Intent intent) {
            super(session, intent);
            this.context = new WeakReference<Context>(context);
        }

        @Override
        protected int internalConnect() {
            Context ctx = context.get();
            if (null != ctx) {
                try {
                    InputStream offlineHtmlInputStream = ctx.getAssets().open("sonic-demo-index.html");
                    responseStream = new BufferedInputStream(offlineHtmlInputStream);
                    return SonicConstants.ERROR_CODE_SUCCESS;
                } catch (Throwable e) {
                    e.printStackTrace();
                }
            }
            return SonicConstants.ERROR_CODE_UNKNOWN;
        }

        @Override
        protected BufferedInputStream internalGetResponseStream() {
            return responseStream;
        }

        @Override
        protected String internalGetCustomHeadFieldEtag() {
            return SonicSessionConnection.CUSTOM_HEAD_FILED_ETAG;
        }

        @Override
        public void disconnect() {
            if (null != responseStream) {
                try {
                    responseStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public int getResponseCode() {
            return 200;
        }

        @Override
        public Map<String, List<String>> getResponseHeaderFields() {
            return new HashMap<>(0);
        }

        @Override
        public String getResponseHeaderField(String key) {
            return "";
        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            if (requestCode == REQUEST_SELECT_FILE) {
                if (uploadMessage == null)
                    return;
                uploadMessage.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, intent));
                uploadMessage = null;
            }
        } else if (requestCode == FILECHOOSER_RESULTCODE) {
            if (null == mUploadMessage)
                return;
            Uri result = intent == null || resultCode != RESULT_OK ? null : intent.getData();
            mUploadMessage.onReceiveValue(result);
            mUploadMessage = null;
        } else {
            Logger.d("上传失败，请重试");
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        webView.onPause();
        webView.pauseTimers();
    }

    @Override
    public void onResume() {
        super.onResume();
        webView.resumeTimers();
        webView.onResume();
    }


    @Override
    protected void onDestroy() {
        webView.destroy();
        webView = null;
        super.onDestroy();
    }
}
